
#include "MainWindow.h"
#include "ProjectDoc.h"
#include "NewFileDialog.h"

#include "GamePluginManager.h"
#include "EditorPlugin.h"
#include "EditorWindow.h"

#include "ui_MainWindow.h"

#include "QLogger.h"


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , mRoot(0)
    , mProjectDoc(0)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    createActions();

    updateMenuBar();
    updateToolBar();
    updateDockBar();

    updateRecentFileActions();
}

MainWindow::~MainWindow()
{
    delete mProjectDoc;
    delete mRoot;
    delete ui;
}

void MainWindow::createActions()
{
    // Recent file
    for (int i = 0; i < MAX_RECENT_FILES; ++i)
    {
        mActRecentFiles[i] = new QAction(this);
        mActRecentFiles[i]->setVisible(false);
        ui->mMenuRecentFiles->addAction(mActRecentFiles[i]);
        connect(mActRecentFiles[i], SIGNAL(triggered()), this, SLOT(onActFileRecentFile()));
    }
}

void MainWindow::updateMenuBar()
{
    bool projectOpened = (mProjectDoc != 0);
    ui->mMenuEdit->menuAction()->setVisible(projectOpened);
    ui->mMenuTool->menuAction()->setVisible(projectOpened);
}

void MainWindow::updateToolBar()
{
    bool projectOpened = (mProjectDoc != 0);
    ui->mToolBarEdit->setVisible(projectOpened);
    ui->mToolBarTool->setVisible(projectOpened);
}

void MainWindow::updateDockBar()
{
    bool projectOpened = (mProjectDoc != 0);
    ui->mDockSolution->setEnabled(projectOpened);
}

void MainWindow::updateRecentFileActions()
{
    QSettings settings;
    QStringList files = settings.value("recentFileList").toStringList();

    int numRecentFiles = qMin(files.size(), (int)MAX_RECENT_FILES);

    for (int i = 0; i < numRecentFiles; ++i)
    {
        QString text = tr("&%1 %2").arg(i + 1).arg(strippedName(files[i]));
        mActRecentFiles[i]->setText(text);
        mActRecentFiles[i]->setData(files[i]);
        mActRecentFiles[i]->setVisible(true);
    }

    for (int j = numRecentFiles; j < MAX_RECENT_FILES; ++j)
    {
        mActRecentFiles[j]->setVisible(false);
    }

    ui->mMenuRecentFiles->setEnabled(numRecentFiles > 0);
}

QString MainWindow::strippedName(const QString &fullFileName)
{
    return QFileInfo(fullFileName).fileName();
}

void MainWindow::setCurrentFile(const QString &filename)
{
    setWindowFilePath(filename);

    QSettings settings;
    QStringList files = settings.value("recentFileList").toStringList();
    settings.remove(filename);
    files.removeAll(filename);
    files.prepend(filename);
    while (files.size() > MAX_RECENT_FILES)
        files.removeLast();

    settings.setValue("recentFileList", files);

    updateRecentFileActions();
}

QWidget *MainWindow::activeMdiChild()
{
    if (QMdiSubWindow *activeSubWindow = ui->mMdiArea->activeSubWindow())
        return activeSubWindow->widget();
    return 0;
}

void MainWindow::createProject(const QString &filename, const QString &folder)
{
    // 创建工程目录
    QDir dir(folder);
    dir.mkpath(folder);

    // 创建工程文档
    mProjectDoc = new ProjectDoc();
    QString path = folder + filename;
    mProjectDoc->create(path);

    // 通知所有插件
    QLoaderList plugins = GamePluginManager::instance().plugins();
    QLoaderList::iterator itr = plugins.begin();
    while (itr != plugins.end())
    {
        EditorPlugin *plugin = qobject_cast<EditorPlugin*>((*itr)->instance());

        if (plugin != 0)
        {
            plugin->onCreateProject(folder);
        }

        ++itr;
    }
}

void MainWindow::openProject(const QString &filename)
{
    QString projPath = filename.left(filename.lastIndexOf("/"));

    if (mProjectDoc == 0)
    {
        mProjectDoc = new ProjectDoc();
    }

    // 打开工程文档
    mProjectDoc->open(filename);

    // 更新界面
    updateMenuBar();
    updateToolBar();
    updateDockBar();

    setCurrentFile(filename);

    populateSolution();

    // 通知所有插件
    QLoaderList plugins = GamePluginManager::instance().plugins();
    QLoaderList::iterator itr = plugins.begin();
    while (itr != plugins.end())
    {
        EditorPlugin *plugin = qobject_cast<EditorPlugin*>((*itr)->instance());

        if (plugin != 0)
        {
            plugin->onOpenProject(projPath, mRoot);
        }

        ++itr;
    }
}

void MainWindow::closeProject()
{
    // 通知所有插件
    QLoaderList plugins = GamePluginManager::instance().plugins();
    QLoaderList::iterator itr = plugins.begin();
    while (itr != plugins.end())
    {
        EditorPlugin *plugin = qobject_cast<EditorPlugin*>((*itr)->instance());

        if (plugin != 0)
        {
            plugin->onCloseProject();
        }

        ++itr;
    }

    delete mRoot;
    mRoot = 0;
    delete mProjectDoc;
    mProjectDoc = 0;

    updateMenuBar();
    updateToolBar();
    updateDockBar();
}

int MainWindow::createFile(const QString &fileName, uint fileType)
{
    EditorPlugin *plugin = GamePluginManager::instance().pluginInstance(fileType);

    if (plugin != 0)
    {
        QString filePath = fileName + "." + plugin->fileExtension();
        return plugin->onCreateFile(filePath);
    }

    return 0;
}

void MainWindow::openFile(const QString &fileName, uint fileType, int userType)
{
    EditorPlugin *plugin = GamePluginManager::instance().pluginInstance(fileType);

    if (plugin != 0)
    {
        // 添加子窗口
        QString filePath = fileName + "." + plugin->fileExtension();
        bool exists = false;
        EditorWindow *editor = plugin->onOpenFile(filePath, this, userType, exists);

        if (editor != 0)
        {
            if (exists)
            {
                // 如果已经存在该窗口，则激活该窗口
                ui->mMdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow*>(editor));
                editor->showMaximized();
            }
            else
            {
                // 窗口不存在，是新创建的窗口，则添加进去
                ui->mMdiArea->addSubWindow(editor);
                editor->showMaximized();
            }

            // 添加子窗口对应的菜单
            QMenu *menu = editor->getMenu();
            ui->mMenuBar->addMenu(menu);
        }
    }
}

void MainWindow::saveFile()
{
    QWidget *w = activeMdiChild();

    EditorWindow *editor = (EditorWindow*)w;
    editor->save();
}

void MainWindow::closeFile()
{

}

void MainWindow::populateSolution()
{
    if (0 == mProjectDoc)
    {
        ui->mTreeSolution->clear();
        return;
    }

    const QString &location = mProjectDoc->location();
    const QString &title = mProjectDoc->title();
    const QString &ext = mProjectDoc->ext();

    QString path = location + title + "." + ext;
    QDir dir(path);
    if (dir.exists(path))
    {
        if (mRoot == 0)
        {
            QTreeWidgetItem *item = new QTreeWidgetItem(ui->mTreeSolution, FT_PROJECT);
            item->setIcon(0, QIcon(":/Icons/Project.png"));
            item->setText(0, title);

            mRoot = item;
        }
    }
}


//--------------------------------------------------------------------------------------------------

void MainWindow::onActFileNew()
{
    QString projPath;

    if (mProjectDoc != 0)
    {
        projPath = mProjectDoc->location();
    }

    NewFileDialog dialog(projPath, this);
    dialog.exec();

    if (dialog.result() == QDialog::Accepted)
    {
        uint fileType = dialog.fileType();
        const QString &fileName = dialog.fileName();
        const QString &fileFolder = dialog.filePath();

        if (FT_PROJECT == fileType)
        {
            closeProject();

            QString path = fileFolder + fileName + QString("/");
            QString name = fileName + QString(".") + QString(PROJECT_EXT);
            QString filePath = path + name;
            createProject(name, path);
            openProject(filePath);
        }
        else
        {
            QString path = fileFolder + fileName;
            QString name = fileName;
            int userType = createFile(path, fileType);
            openFile(path, fileType, userType);
        }
    }
}

void MainWindow::onActFileOpen()
{
    QString filePath = QFileDialog::getOpenFileName(this, tr("Select GameEditor Project File"),
        QDir::currentPath(), tr("GameEditor Project File (*.vproj)"));

    if (!filePath.isEmpty())
    {
        closeProject();
        openProject(filePath);
    }
}

void MainWindow::onActFileSave()
{
    saveFile();
}

void MainWindow::onActFileSaveAs()
{

}

void MainWindow::onActFileSaveAll()
{

}

void MainWindow::onActFileClose()
{

}

void MainWindow::onActFileRename()
{

}

void MainWindow::onActFileRecentFile()
{
    QAction *action = qobject_cast<QAction *>(sender());
    if (action)
    {
        QString fileName = action->data().toString();
        closeProject();
        openProject(fileName);
    }
}

void MainWindow::onActFileExit()
{
    close();
}

void MainWindow::onActEditUndo()
{

}

void MainWindow::onActEditRedo()
{

}

void MainWindow::onActEditCut()
{

}

void MainWindow::onActEditCopy()
{

}

void MainWindow::onActEditPaste()
{

}

void MainWindow::onActEditDel()
{

}

void MainWindow::onActViewToolBar(bool checked)
{

}

void MainWindow::onActViewStatusBar(bool checked)
{

}

void MainWindow::onActViewSlnExplorer(bool checked)
{
    ui->mDockSolution->setVisible(checked);
}

void MainWindow::onActToolExport()
{

}

void MainWindow::onActToolImport()
{

}

void MainWindow::onActHelpManual()
{

}

void MainWindow::onActHelpAbout()
{

}

void MainWindow::onSlnItemDblClicked(QTreeWidgetItem *item, int column)
{
    QString name = item->text(column);
    int fileType = item->data(0, Qt::UserRole).toInt();

    if (FT_PROJECT == fileType)
    {
    }
    else
    {
        EditorPlugin *plugin = GamePluginManager::instance().pluginInstance(fileType);
        if (plugin != 0)
        {
            int userType = item->type();
            QString filePath = mProjectDoc->location() + plugin->fileFolder() + "/" + name;
            openFile(filePath, fileType, userType);
        }
    }
}
